import React from "react";
import { Link, useLocation } from "react-router-dom";
import "./index.less";
import logo from "./../../pages/Login/images/favicon.png";
// 左侧导航栏不写死,使用menuList数据来动态生成
import menuList from "../../config/menuConfig";
import { Menu } from "antd";
import { connect } from "react-redux";
import {
  // 引入icon
  HomeOutlined,
  HeartTwoTone,
  TableOutlined,
  DatabaseOutlined,
  AreaChartOutlined,
  PieChartOutlined,
  LineChartOutlined,
  BarChartOutlined,
  ShopOutlined,
  UserSwitchOutlined,
  UsergroupDeleteOutlined,
} from "@ant-design/icons";
import memory from "../../utils/memoryUtils";
import { setHeadTitle } from "../../redux/action";

const { SubMenu } = Menu;

// memuList接口 children数组内部的和外面的一样 所以也是用obj
interface obj {
  title: string;
  key: string;
  icon: string;
  isPublic?: Boolean;
  children?: Array<obj>;
}

// LeftNav组件开始写
const LeftNav: React.FC = (props: any) => {
  //功能函数 确定当前登录用户对item是否拥有权限
  const hasAuth = (item: any) => {
    const { isPublic, key } = item;

    const menus = memory.user.role.menus;
    const username = memory.user.username;

    // 1 当前用户是admin 拥有所有权限
    // 2 如果当前item是公开的
    // 3 当前用户拥有item权限 (key有没有在menu中)

    // 但是如果只拥有一个item下面的一个item的时候 整个item就不会显示 所以要经过判断4
    if (username === "admin" || isPublic || menus.indexOf(key) !== -1) {
      return true;
    } else if (item.children) {
      // 4 如果当前用户有此item的某个子item权限 这样就能显示出item下某个子item的值了
      // 前面加上!!可以将结果强制转换为布尔值
      return !!item.children.find(
        (child: any) => menus.indexOf(child.key) !== 1
      );
    }
    return false;
  };
  // ---------------------------------------------------------
  // 从外部读取数据来渲染左侧导航栏,不能写死,用读取数据渲染才能实现权限功能
  const getMenuList = (menuList: Array<obj>) => {
    // eslint-disable-next-line array-callback-return
    return menuList.map((item: obj) => {
      // 如果用户有item对应的权限才要渲染加载对应的菜单功能
      // console.log(item);

      if (hasAuth(item)) {
        if (item.children) {
          // if (hasAuth(item)) {
          // 先获取item.icon直接生成一个icon图标 在下面添加到SubMenu属性中
          // 因为直接写在SubMenu属性中会因为ts类型中string不能索引而出错
          // const icon = <item.icon />;
          // console.log(icon);
          // console.log(item.icon);
          // 动态生成不太会写 只能用这种比较原始比较的方法来写了 提前生成JSX的icon标签 直接插入到Menu.Item属性icon中
          // 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串
          // 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里
          let icon: any = undefined;
          if (item.icon === "TableOutlined") {
            icon = <TableOutlined />;
          } else if (item.icon === "HomeOutlined") {
            icon = <HomeOutlined />;
          } else if (item.icon === "ShopOutlined") {
            icon = <ShopOutlined />;
          } else if (item.icon === "DatabaseOutlined") {
            icon = <DatabaseOutlined />;
          } else if (item.icon === "PieChartOutlined") {
            icon = <PieChartOutlined />;
          } else if (item.icon === "BarChartOutlined") {
            icon = <BarChartOutlined />;
          } else if (item.icon === "LineChartOutlined") {
            icon = <LineChartOutlined />;
          } else if (item.icon === "AreaChartOutlined") {
            icon = <AreaChartOutlined />;
          }
          return (
            //如果item有children,就渲染在submenu中
            // 如果item有children,递归调用getMenuList继续渲染出内部的所有item直到没有children
            <SubMenu key={item.key} icon={icon} title={item.title}>
              {/* 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串 */}
              {/* 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里 */}
              {getMenuList(item.children)}
            </SubMenu>
          );
        } else {
          // 动态生成不太会写 只能用这种比较原始比较的方法来写了 提前生成JSX的icon标签 直接插入到Menu.Item属性icon中
          // 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串
          // 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里

          let icon: any = undefined;
          if (item.icon === "TableOutlined") {
            icon = <TableOutlined />;
          } else if (item.icon === "HomeOutlined") {
            icon = <HomeOutlined />;
          } else if (item.icon === "DatabaseOutlined") {
            icon = <DatabaseOutlined />;
          } else if (item.icon === "ShopOutlined") {
            icon = <ShopOutlined />;
          } else if (item.icon === "UserSwitchOutlined") {
            icon = <UserSwitchOutlined />;
          } else if (item.icon === "UsergroupDeleteOutlined") {
            icon = <UsergroupDeleteOutlined />;
          } else if (item.icon === "PieChartOutlined") {
            icon = <PieChartOutlined />;
          } else if (item.icon === "BarChartOutlined") {
            icon = <BarChartOutlined />;
          } else if (item.icon === "LineChartOutlined") {
            icon = <LineChartOutlined />;
          } else if (item.icon === "AreaChartOutlined") {
            icon = <AreaChartOutlined />;
          }

          return (
            // item没有children就直接一层渲染不需要submenu
            <Menu.Item key={item.key} icon={icon}>
              <Link
                // 这里点击侧边栏的nav会触发redux的方法 从而dispatch一个action
                // 实现对redux store中titlename的修改
                onClick={() => {
                  props.setHeadTitle(item.title);
                }}
                to={item.key}
              >
                {item.title}
              </Link>
            </Menu.Item>
          );
        }
      }
      // }
      // if (item.children) {
      //   // 先获取item.icon直接生成一个icon图标 在下面添加到SubMenu属性中
      //   // 因为直接写在SubMenu属性中会因为ts类型中string不能索引而出错
      //   // const icon = <item.icon />;
      //   // console.log(icon);
      //   // console.log(item.icon);
      //   // 动态生成不太会写 只能用这种比较原始比较的方法来写了 提前生成JSX的icon标签 直接插入到Menu.Item属性icon中
      //   // 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串
      //   // 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里
      //   let icon: any = undefined;
      //   if (item.icon === "TableOutlined") {
      //     icon = <TableOutlined />;
      //   } else if (item.icon === "HomeOutlined") {
      //     icon = <HomeOutlined />;
      //   } else if (item.icon === "ShopOutlined") {
      //     icon = <ShopOutlined />;
      //   } else if (item.icon === "DatabaseOutlined") {
      //     icon = <DatabaseOutlined />;
      //   } else if (item.icon === "PieChartOutlined") {
      //     icon = <PieChartOutlined />;
      //   } else if (item.icon === "BarChartOutlined") {
      //     icon = <BarChartOutlined />;
      //   } else if (item.icon === "LineChartOutlined") {
      //     icon = <LineChartOutlined />;
      //   } else if (item.icon === "AreaChartOutlined") {
      //     icon = <AreaChartOutlined />;
      //   }
      //   return (
      //     //如果item有children,就渲染在submenu中
      //     // 如果item有children,递归调用getMenuList继续渲染出内部的所有item直到没有children
      //     <SubMenu key={item.key} icon={icon} title={item.title}>
      //       {/* 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串 */}
      //       {/* 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里 */}
      //       {getMenuList(item.children)}
      //     </SubMenu>
      //   );
      // } else {
      //   // 动态生成不太会写 只能用这种比较原始比较的方法来写了 提前生成JSX的icon标签 直接插入到Menu.Item属性icon中
      //   // 这里icon={icon}本来也是应该写成icon={item.icon}的形式,但是会直接渲染成icon对应的字符串
      //   // 因为antd4中 icon={}里面要直接写整个标签 所以没办法了 在上面对item.icon先作判断然后直接生成JSX标签插入到这里
      //   let icon: any = undefined;
      //   if (item.icon === "TableOutlined") {
      //     icon = <TableOutlined />;
      //   } else if (item.icon === "HomeOutlined") {
      //     icon = <HomeOutlined />;
      //   } else if (item.icon === "DatabaseOutlined") {
      //     icon = <DatabaseOutlined />;
      //   } else if (item.icon === "ShopOutlined") {
      //     icon = <ShopOutlined />;
      //   } else if (item.icon === "UserSwitchOutlined") {
      //     icon = <UserSwitchOutlined />;
      //   } else if (item.icon === "UsergroupDeleteOutlined") {
      //     icon = <UsergroupDeleteOutlined />;
      //   } else if (item.icon === "PieChartOutlined") {
      //     icon = <PieChartOutlined />;
      //   } else if (item.icon === "BarChartOutlined") {
      //     icon = <BarChartOutlined />;
      //   } else if (item.icon === "LineChartOutlined") {
      //     icon = <LineChartOutlined />;
      //   } else if (item.icon === "AreaChartOutlined") {
      //     icon = <AreaChartOutlined />;
      //   }

      //   return (
      //     // item没有children就直接一层渲染不需要submenu
      //     <Menu.Item key={item.key} icon={icon}>
      //       <Link to={item.key}>{item.title}</Link>
      //     </Menu.Item>
      //   );
      // }
    });
  };
  // ---------------------------------------------------------

  // ---------------------------------------------------------
  // 获取当前所在的路径
  // 根据当前所在的路径来高亮侧边栏的item 用useLocation来获取pathname
  const location = useLocation();
  let Currentpath = location.pathname;
  // console.log("before:", Currentpath);
  // // 下面是给product子路由配置  当当前路径是product下的子路由时候 也高亮product选项
  // // 否则如果当前路径是在product下的子路由,侧边就没办法对于当前路径,就没办法高亮product选项了
  // 用来匹配当前路由是否是/admin/product子路由的数组
  const pathProduct = [
    "/admin/product/home",
    "/admin/product/detail",
    "/admin/product/update",
  ];

  // ---------------------------------------------------------

  // ---------------------------------------------------------
  // 这里是要根据当前路径(也就是选择的侧边栏条目)对对应的侧边栏submenu条目进行打开

  const charts: Array<string> = [
    // 两个数组常量 记录的是两个submenu内部的条目 用于匹配的
    "/admin/charts/bar",
    "/admin/charts/pie",
    "/admin/charts/line",
  ];
  // 两个数组常量 记录的是两个submenu内部的条目 用于匹配的
  const product: Array<string> = [
    "/admin/category",
    "/admin/product",
    "/admin/product/home",
    "/admin/product/detail",
    "/admin/product/update",
  ];
  // openMenu存的是当前需要打开的submenu的名称
  let openMenu: string = "";
  // 要打开的两个submenu直接搞成常量
  const OpenCharts = "/admin/charts";
  const OpenProduct = "/admin/products";
  // console.log(openMenu);
  // 用的是比较简单的判断方式 如果当前所在路径是 /charts/* 中的任意一个路径  就设置openMenu为 /admin/charts 就默认打开/admin/charts的Submenu
  if (charts.includes(Currentpath)) openMenu = OpenCharts;
  // 用的是比较简单的判断方式 如果当前所在路径是 /product/* 中的任意一个路径  就设置openMenu为 /admin/charts 就默认打开/admin/products的Submenu
  else if (product.includes(Currentpath)) openMenu = OpenProduct;

  // useEffect(() => {
  //   const OpenCharts = "/admin/charts";
  //   const OpenProduct = "/admin/products";

  //   // 用的是比较简单的判断方式 如果当前所在路径是 /charts/* 中的任意一个路径  就设置openMenu为 /admin/charts 就默认打开/admin/charts的Submenu
  //   if (charts.includes(Currentpath)) openMenu = OpenCharts;
  //   // 用的是比较简单的判断方式 如果当前所在路径是 /product/* 中的任意一个路径  就设置openMenu为 /admin/charts 就默认打开/admin/products的Submenu
  //   else if (product.includes(Currentpath)) openMenu = OpenProduct;
  //   console.log(openMenu);
  //   return () => {};
  // }, [Currentpath, openMenu]);
  // ---------------------------------------------------------

  return (
    <div className="left-nav">
      <Link to="/admin/home" className="left-nav-header">
        <img src={logo} alt="" />
        <h1>管理页面</h1>
        <span className="heart-logo">
          <HeartTwoTone twoToneColor="#66ccff" />
        </span>
      </Link>
      <div className="left-nav-container" style={{ width: 200 }}>
        <Menu
          // 要动态的根据请求的路径对侧边栏的menu高亮
          // 根据当前所在的路径来高亮侧边栏的item 用useLocation来获取pathname

          // 高亮选项 如果当前路由在/admin/product的子路由 比如/admin/product/home 那么也高亮/admin/product对应的选项
          // 如果当前路由是子路由 那么高亮/admin/product对应的选项
          defaultSelectedKeys={
            pathProduct.includes(location.pathname)
              ? ["/admin/product"]
              : [location.pathname]
          }
          // 默认展开的submenu 根据当前路径选择判断
          defaultOpenKeys={[openMenu]}
          mode="inline"
          theme="dark"
        >
          {/* menu的内容有menuList来动态生成而不是写死的方法了 */}
          {/* <Menu.Item key="1" icon={<HomeOutlined />}>
            <Link to="/admin/home">首页</Link>
          </Menu.Item> */}

          {/* <SubMenu key="sub1" icon={<InsertRowBelowOutlined />} title="商品">
            <Menu.Item key="s1" icon={<PieChartOutlined />}>
              <Link to="/admin/category">品类管理</Link>
            </Menu.Item>
            <Menu.Item key="s2" icon={<PieChartOutlined />}>
              <Link to="/admin/product">品类管理</Link>
            </Menu.Item>
            <Menu.Item key="s3">待定...</Menu.Item>
            <Menu.Item key="s4">待定...</Menu.Item>
          </SubMenu> */}

          {/* getMenuList动态生成左侧的submenu和menu.item */}
          {getMenuList(menuList)}
        </Menu>
      </div>
    </div>
  );
};

// 把store中的dispatch映射为一般方法
const mapDispatchToProps = (dispatch: any) => {
  return {
    setHeadTitle: (title: any) => {
      dispatch(setHeadTitle(title));
    },
  };
};
// react-redux的connect把ui组件和状态连接起来
export default connect(
  // 因为left-bav组件不涉及状态的显示  所以这里只需要一mapDispatchToProps即可 下面对应mapStateToProps中并没有转换任何的redux中的状态
  (state: any) => ({}),
  //mapDispatchToProps 把store中的dispatch映射为一般方法传给组件的props 组件中可以直调用props.setHeadTitle()
  mapDispatchToProps
)(LeftNav);
